package com.cmes.system.core.aspect;

import com.cmes.core.annotation.OperateLog;
import com.cmes.core.context.security.SecurityContextHolder;
import com.cmes.core.exception.ApplicationException;
import com.cmes.core.utils.AsyncUtils;
import com.cmes.core.utils.JsonUtils;
import com.cmes.system.core.entity.OperateLogEntity;
import com.cmes.system.core.service.OperateLogService;
import lombok.RequiredArgsConstructor;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import javax.servlet.http.HttpServletRequest;

/**
 * 操作日志
 *
 * @author Bruce.Gong
 * @since 1.0.0-SNAPSHOT
 */
@RequiredArgsConstructor
@Aspect
@Component
public class OperateLogAspect {

    private final OperateLogService operateLogService;

    @Around(value = "@annotation(operateLog)")
    public Object around(ProceedingJoinPoint joinPoint , OperateLog operateLog) {
        long start = System.currentTimeMillis();
        ServletRequestAttributes requestAttributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
        HttpServletRequest request = requestAttributes == null ? null : requestAttributes.getRequest();
        OperateLogEntity log = new OperateLogEntity();
        log.setUserId(SecurityContextHolder.getCurrentUserId());
        log.setModule(operateLog.module());
        log.setOperate(operateLog.businessType());
        log.setReqUrl(request == null ? "" : request.getRequestURI());
        log.setReqMethod(request == null ? "" : request.getMethod());
        log.setReqParams(JsonUtils.serializer(joinPoint.getArgs()));

        Object proceed;
        try {
            proceed = joinPoint.proceed();
        } catch(ApplicationException e) {
            throw e;
        } catch (Throwable e) {
            throw new RuntimeException(e);
        }
        long cost = System.currentTimeMillis() - start;
        log.setCost(cost);
        log.setResParams(JsonUtils.serializer(proceed));
        AsyncUtils.run(() -> operateLogService.insert(log));
        return proceed;
    }

}
